﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CapstoneProjectAEReader.Common.Utility;
using CapstoneProjectAEReader.Entities.Models;
using CapstoneProjectAEReader.DataAccess.DBAccess;
using CapstoneProjectAEReader.GUIs.Others;
using CapstoneProjectAEReader.Business.Others;
using System.Linq;
using Microsoft.Win32;
using System.IO;

namespace CapstoneProjectAEReader.GUIs.LibraryGUI
{
    /// <summary>
    /// Interaction logic for LocalLibrary.xaml
    /// </summary>
    public partial class LocalLibrary : UserControl
    {
        #region Attributes

        private DAO _dao;
        private MainWindow _mainWindow;
        private EbookGroup _ebookGroup;

        private const string Search = "search";
        private const string Sort = "sort";
        private const string AddGroup = "addGroup";
        private const string DeleteGroup = "deleteGroup";
        private const string AddEbook = "addEbook";
        private const string DeleteEbook = "deleteEbook";
        private const string UpdateEbook = "editEbook";
        private const string Group = "group";
        private const string RecentRead = "recentRead";
        private const string Alphabet = "alphabet";
        private const string DateTimeLb = "datetime";
        private const string BookList = "bookList";
        private const string TitleOrder = "titleOrder";
        private const string AuthorOrder = "authorOrder";
        private const string PublisherOrder = "publisherOrder";
        private const string InvalidDateTime = "invalidDateTime";
        private const string SelectGroupWarn = "selectGroupWarn";
        private const string EditGroup = "editGroup";
        private const string SelectEbookWarn = "selectEbookWarn";
        private const string ExportEbook = "exportEbook";
        private const string ExportSuccess = "exportSuccess";
        private const string DeletedEbook = "ebookInvalidPath";
        private const string EbookExisted = "ebookExisted";
        private const string DeleteGroupConfirmation = "deleteGroupConfirmation";
        private const string DeleteEbookConfirmation = "deleteEbookDetailConfirmation";
        private const string OpenEbook = "statusOpenind";
        private const string GroupItemTemplate = "GroupItemTemplate";
        private const string BookCategoryUri = @"pack://application:,,,/GUIs/LibraryGUI/Image/BookCategory.png";
        private const string NullCircle = "Image/NULLCircle.png";
        private const string PdfCircle = "Image/PDFCircle.png";
        private const string EpubCircle = "Image/EPUBCircle.png";
        private const string FileIcon = "Image/file.png";
        private const string PdfIcon = "Image/PDF.png";
        private const string EpubIcon = "Image/ePUB.png";
        private const string RemoveFromList = "removeFromList";
        private const string OpenNewEbook = "openFileButton";
        private const string CannotDeleteGroup = "notDeleteGroup";
        private const string DeleteOpeningEbook = "deleteOpeningEbook";
        private const string SearchEbook = "searchEbook";
        private const string OpenEbookError = "openEbookError";
        private const string CannotUpdateGroup = "notUpdateGroup";
        private const string UpdateEbookError = "updateEbookError";
        private const string AddEbookError = "addEbookError";
        private const string FormTitle = "ebookFormTitle";

        #endregion

        public LocalLibrary(DTO dto, MainWindow mainWindows)
        {
            _dao = new DAO(dto);
            _mainWindow = mainWindows;
            InitializeComponent();
            ReloadFormLanguage();
            RebindGroupData();
            RebindRecentReadData();
        }

        public void ReloadFormLanguage()
        {
            lbSearch.Content = ResourceReader.GetResourceContent(Search);
            lbGroup.Content = ResourceReader.GetResourceContent(Group);
            lbAddGroup.Content = ResourceReader.GetResourceContent(AddGroup);
            lbDeleteGroup.Content = ResourceReader.GetResourceContent(DeleteGroup);
            lbRecentRead.Content = ResourceReader.GetResourceContent(RecentRead);
            lbBookList.Content = ResourceReader.GetResourceContent(BookList);
            lbAddBook.Content = ResourceReader.GetResourceContent(AddEbook);
            lbEditBook.Content = ResourceReader.GetResourceContent(UpdateEbook);
            lbDeleteBook.Content = ResourceReader.GetResourceContent(DeleteEbook);
            lbExportBook.Content = ResourceReader.GetResourceContent(ExportEbook);
            List<ComboBoxItem> cbItems = new List<ComboBoxItem>();
            ComboBoxItem temp = new ComboBoxItem();
            temp.Content = ResourceReader.GetResourceContent(TitleOrder);
            cbItems.Add(temp);
            temp = new ComboBoxItem();
            temp.Content = ResourceReader.GetResourceContent(AuthorOrder);
            cbItems.Add(temp);
            temp = new ComboBoxItem();
            temp.Content = ResourceReader.GetResourceContent(PublisherOrder);
            cbItems.Add(temp);
            cbSearch.ItemsSource = cbItems;
            cbSearch.SelectedIndex = 0;
            lbEditGroup.Content = ResourceReader.GetResourceContent(EditGroup);
            var recentCtMenu = (ContextMenu) Resources["RecentReadContextMenu"];
            MenuItem tempMenu = (MenuItem) recentCtMenu.Items[0];
            tempMenu.Header = ResourceReader.GetResourceContent(OpenNewEbook);
            tempMenu = (MenuItem) recentCtMenu.Items[1];
            tempMenu.Header = ResourceReader.GetResourceContent(RemoveFromList);
            var groupCtMenu = (ContextMenu) Resources["GroupContextMenu"];
            tempMenu = (MenuItem) groupCtMenu.Items[0];
            tempMenu.Header = ResourceReader.GetResourceContent(EditGroup);
            tempMenu = (MenuItem) groupCtMenu.Items[1];
            tempMenu.Header = ResourceReader.GetResourceContent(DeleteGroup);
            btSearch.ToolTip = ResourceReader.GetResourceContent(SearchEbook);
            lbLibraryForm.Content = ResourceReader.GetResourceContent(FormTitle);
        }

        public void RebindBookListData(List<EbookGroup> groups)
        {
            if (groups.Count > 0)
            {
                List<Ebook> bindingList = new List<Ebook>();
                foreach (var item in _dao.Dto.Ebooks)
                {
                    foreach (var group in item.Group)
                    {
                        if (groups.Any(e => e.Groupname == group))
                        {
                            if (!bindingList.Contains(item))
                            {
                                bindingList.Add(item);
                                break;
                            }
                        }
                    }
                }
                listBook.ItemsSource = TransformEbook(bindingList);
            }
            else
            {
                listBook.ItemsSource = null;
            }
        }

        public void RebindGroupData()
        {
            GroupTreeView.Items.Clear();
            NewTreeViewItem temp;
            foreach (var group in _dao.Dto.EbookGroup)
            {
                string getHeader = String.Format(Constants.GroupTemplate, group.Groupname, _dao.CountMembers(group));
                temp = new NewTreeViewItem(getHeader);

                temp.ItemsSource = TransformBookInGroup(_dao.GetEbookOfGroup(group), group);
                temp.ItemTemplate = FindResource(GroupItemTemplate) as DataTemplate;
                GroupTreeView.Items.Add(temp);
            }
        }

        private class NewTreeViewItem : TreeViewItem
        {
            private Image _image = null;
            private Label _label = null;
            public string ItemHeader;

            public NewTreeViewItem(string header)
            {
                StackPanel panel = new StackPanel();
                panel.Orientation = Orientation.Horizontal;
                ItemHeader = header;
                _image = new Image();
                _image.Source = new BitmapImage(new Uri(BookCategoryUri));

                _image.VerticalAlignment = VerticalAlignment.Center;
                _image.Height = 24;
                _image.Width = 24;
                panel.Children.Add(_image);

                _label = new Label();
                _label.Content = header;
                _label.FontSize = 15;
                _label.Margin = new Thickness(2, 0, 0, 0);
                _label.FontWeight = FontWeights.SemiBold;
                _label.VerticalAlignment = VerticalAlignment.Center;
                panel.Children.Add(_label);
                Header = panel;
            }
        }

        private List<BookInGroup> TransformBookInGroup(List<Ebook> source, EbookGroup group)
        {
            List<BookInGroup> rtList = new List<BookInGroup>();
            BookInGroup temp;
            foreach (var ebook in source)
            {
                temp = new BookInGroup();
                temp.Parent = group;
                temp.Source = ebook;
                temp.BookName = ebook.Title;
                string iconPath = NullCircle;
                temp.FileType = iconPath;
                if (ebook.Type == Constants.EbookType.Pdf)
                {
                    iconPath = PdfCircle;
                    temp.FileType = iconPath;
                }
                else if (ebook.Type == Constants.EbookType.Epub)
                {
                    iconPath = EpubCircle;
                    temp.FileType = iconPath;
                }
                rtList.Add(temp);
            }
            return rtList;
        }

        public void RebindRecentReadData()
        {
            tvRecentRead.ItemsSource = null;
            tvRecentRead.ItemsSource = TransformEbook(_dao.Dto.SettingDetail.RecentRead);
        }

        private void HandleAddEbookGroup(object sender, RoutedEventArgs e)
        {
            AddItems newGroupWindow = new AddItems(_dao.Dto);
            newGroupWindow.SetFormTitle("New Group");
            if (newGroupWindow.ShowDialog() == true)
            {
                RebindGroupData();
            }
        }

        private void HandleDoubleClickGroup(object sender, RoutedEventArgs e)
        {
            EbookGroup selectedGroup = new EbookGroup();
            if (GroupTreeView.SelectedItem != null)
            {
                try
                {
                    NewTreeViewItem selectedTreeViewItem = (NewTreeViewItem) ((TreeView) sender).SelectedItem;
                    string groupName =
                        selectedTreeViewItem.ItemHeader.Split(Constants.CommonCharacters.NgoacDon)[0];
                    _ebookGroup = _dao.SelectEbookGroup(groupName);
                    //AddItems updateGroupWindow = new AddItems(_dao.Dto, selectedGroup);
                    //if (updateGroupWindow.ShowDialog() == true)
                    //{
                    //    RebindGroupData();
                    //}
                }
                catch (Exception)
                {
                    BookInGroup selectedTreeViewItem = (BookInGroup) ((TreeView) sender).SelectedItem;
                    _ebookGroup = selectedTreeViewItem.Parent;
                    Message temp =
                        new Message(String.Format(ResourceReader.GetResourceContent(OpenEbook),
                                                  selectedTreeViewItem.Source.Title));
                    temp.Show();
                    _mainWindow.OpenNewEbook(selectedTreeViewItem.Source.Path, 0);
                    temp.Close();
                }
            }
        }

        private void HandleOpenEbookInGroup(object sender, RoutedEventArgs e)
        {
            try
            {
                if (GroupTreeView.SelectedItem != null)
                {
                    BookInGroup selectedTreeViewItem = (BookInGroup) ((TreeView) sender).SelectedItem;
                    _ebookGroup = selectedTreeViewItem.Parent;
                    Message temp =
                        new Message(String.Format(ResourceReader.GetResourceContent(OpenEbook),
                                                  selectedTreeViewItem.Source.Title));
                    temp.Show();
                    _mainWindow.OpenNewEbook(selectedTreeViewItem.Source.Path, 0);
                    temp.Close();
                }
            }
            catch (Exception ex)
            {
                Utilities.ShowErrorMesBox(String.Format(ResourceReader.GetResourceContent(OpenEbookError), ex.Message));
            }
        }

        private void HandleRemoveEbookInGroup(object sender, RoutedEventArgs e)
        {
            if (GroupTreeView.SelectedItem != null)
            {
                BookInGroup selectedTreeViewItem = (BookInGroup) ((TreeView) sender).SelectedItem;
                _ebookGroup = selectedTreeViewItem.Parent;
                _dao.RemoveGroupOfEbook(selectedTreeViewItem.Source, _ebookGroup);
                RebindGroupData();
                RebindBookListData(new List<EbookGroup> {_ebookGroup});
            }
        }

        private void HandleDeleteEbookGroup(object sender, RoutedEventArgs e)
        {
            if (GroupTreeView.SelectedItem != null)
            {
                if (MessageBoxResult.OK ==
                    Utilities.ShowConfirmationMesBox(ResourceReader.GetResourceContent(DeleteGroupConfirmation)))
                {
                    EbookGroup selectedGroup = new EbookGroup();
                    try
                    {
                        NewTreeViewItem selectedTreeViewItem = (NewTreeViewItem) GroupTreeView.SelectedItem;
                        string groupName = selectedTreeViewItem.ItemHeader.Split(Constants.CommonCharacters.NgoacDon)[0];
                        selectedGroup = _dao.SelectEbookGroup(groupName);
                    }
                    catch (Exception)
                    {
                        BookInGroup selectedTreeViewItem = (BookInGroup) GroupTreeView.SelectedItem;
                        selectedGroup = selectedTreeViewItem.Parent;
                    }
                    if (!Constants.UnGroup.Equals(selectedGroup.Groupname))
                    {
                        _dao.DeleteEbookGroup(selectedGroup);
                    }
                    else
                    {
                        Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(CannotDeleteGroup));
                    }
                    RebindGroupData();
                    RebindBookListData(new List<EbookGroup> {_ebookGroup});
                }
            }
            else
            {
                Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(SelectGroupWarn));
            }
        }

        private void HandleDbMouseClickTvRecentRead(object sender, RoutedEventArgs e)
        {
            if (tvRecentRead.SelectedItem != null)
            {
                EbookForDisplay selectedItem = (EbookForDisplay) tvRecentRead.SelectedItem;
                if (File.Exists(selectedItem.Ebook.Path))
                {
                    Message temp =
                        new Message(String.Format(ResourceReader.GetResourceContent(OpenEbook), selectedItem.Title));
                    temp.Show();
                    _mainWindow.OpenNewEbook(selectedItem.Ebook.Path, 0);
                    temp.Close();
                }
                else
                {
                    Utilities.ShowErrorMesBox(ResourceReader.GetResourceContent(DeletedEbook));
                }
            }
        }

        private void HandleRemoveRecentReadItem(object sender, RoutedEventArgs e)
        {
            if (tvRecentRead.SelectedItem != null)
            {
                EbookForDisplay selectedItem = (EbookForDisplay) tvRecentRead.SelectedItem;
                _dao.RemoveRecentReadItem(selectedItem.Ebook);
                RebindRecentReadData();
            }
        }

        private void HandleBtExportBook(object sender, RoutedEventArgs e)
        {
            if (listBook.SelectedItems.Count == 1)
            {
                EbookForDisplay selectedItem = (EbookForDisplay) listBook.SelectedItem;
                EbookDetailExporter exporter = new EbookDetailExporter(_dao.Dto);
                SaveFileDialog saveFileDlg = new SaveFileDialog();
                saveFileDlg.Filter = Constants.FileFilter.FileExporter;
                if (saveFileDlg.ShowDialog() == true)
                {
                    string extension = System.IO.Path.GetExtension(saveFileDlg.FileName);
                    if (extension.Equals(".doc") || extension.Equals(".docx"))
                    {
                        exporter.CreateMsWord(_dao, selectedItem.Ebook.Id, saveFileDlg.FileName);
                        Utilities.ShowSuccessfulMesbox(ResourceReader.GetResourceContent(ExportSuccess));
                    }
                    else if (extension.Equals(".pdf"))
                    {
                        exporter.CreatePdf(_dao, selectedItem.Ebook.Id, saveFileDlg.FileName);
                        Utilities.ShowSuccessfulMesbox(ResourceReader.GetResourceContent(ExportSuccess));
                    }
                }
            }
            else
            {
                Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(SelectEbookWarn));
            }
        }

        private void HandleEditEbookGroup(object sender, RoutedEventArgs e)
        {
            if (GroupTreeView.SelectedItem != null)
            {
                EbookGroup selectedGroup = new EbookGroup();
                try
                {
                    NewTreeViewItem selectedTreeViewItem = (NewTreeViewItem) GroupTreeView.SelectedItem;
                    string groupName = selectedTreeViewItem.ItemHeader.Split(Constants.CommonCharacters.NgoacDon)[0];
                    selectedGroup = _dao.SelectEbookGroup(groupName);
                }
                catch (Exception)
                {
                    BookInGroup selectedTreeViewItem = (BookInGroup) GroupTreeView.SelectedItem;
                    selectedGroup = selectedTreeViewItem.Parent;
                }
                if (!Constants.UnGroup.Equals(selectedGroup.Groupname))
                {
                    AddItems updateGroupWindow = new AddItems(_dao.Dto, selectedGroup);
                    updateGroupWindow.SetFormTitle("Update Group");
                    if (updateGroupWindow.ShowDialog() == true)
                    {
                        RebindGroupData();
                        RebindBookListData(new List<EbookGroup> {_ebookGroup});
                    }
                }
                else
                {
                    Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(CannotUpdateGroup));
                }
            }
            else
            {
                Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(SelectGroupWarn));
            }
        }

        public List<EbookGroup> GetCheckedItem()
        {
            List<EbookGroup> rtList = new List<EbookGroup>();
            if (_ebookGroup != null)
            {
                rtList.Add(_ebookGroup);
            }
            return rtList;
        }

        public Grid GetLibraryTab()
        {
            return LibraryGrid;
        }

        private void HandleBtSearch(object sender, RoutedEventArgs e)
        {
            string searchedText = txtSearch.Text.Trim();
            ComboBoxItem selectedItem = (ComboBoxItem) cbSearch.SelectedItem;
            if (selectedItem.Content.Equals(ResourceReader.GetResourceContent(AuthorOrder)))
            {
                List<Ebook> selectedEbook = _dao.SearchEbookByAuthor(searchedText);
                listBook.ItemsSource = TransformEbook(selectedEbook);
            }

            if (selectedItem.Content.Equals(ResourceReader.GetResourceContent(TitleOrder)))
            {
                List<Ebook> selectedEbook = _dao.SearchEbookByTitle(searchedText);
                listBook.ItemsSource = TransformEbook(selectedEbook);
            }
            if (selectedItem.Content.Equals(ResourceReader.GetResourceContent(PublisherOrder)))
            {
                List<Ebook> selectedEbook = _dao.SearchEbookByPublisher(searchedText);
                listBook.ItemsSource = TransformEbook(selectedEbook);
            }
        }

        private void HandleDoubleClick(object sender, RoutedEventArgs e)
        {
            if (listBook.SelectedItems.Count == 1)
            {
                EbookForDisplay selectedItem = (EbookForDisplay) listBook.SelectedItem;
                Message temp =
                    new Message(String.Format(ResourceReader.GetResourceContent(OpenEbook), selectedItem.Title));
                temp.Show();
                _mainWindow.OpenNewEbook(selectedItem.Ebook.Path, 0);
                temp.Close();
            }
        }

        private void HandleBtDeleteEbook(object sender, RoutedEventArgs e)
        {
            if (listBook.SelectedItems.Count == 1)
            {
                EbookForDisplay selectedItem = (EbookForDisplay) listBook.SelectedItem;
                if (!_mainWindow.CheckTabExist(selectedItem.Ebook.Title))
                {
                    if (MessageBoxResult.OK ==
                        Utilities.ShowConfirmationMesBox(ResourceReader.GetResourceContent(DeleteEbookConfirmation)))
                    {
                        _dao.DeleteEbook(selectedItem.Ebook);
                        Utilities.DeleteFile(selectedItem.Ebook.Path);
                        Utilities.DeleteFile(selectedItem.Ebook.BookmarkPath);
                        Utilities.DeleteFile(selectedItem.Ebook.BookmarkPath.Replace(Constants.XmlExtension,
                                                                                     Constants.PngExtension));
                        List<EbookGroup> temp = GetCheckedItem();
                        RebindGroupData();
                        RebindBookListData(temp);
                    }
                }
                else
                {
                    Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(DeleteOpeningEbook));
                }
            }
            else
            {
                Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(SelectEbookWarn));
            }
        }

        private void HandleEditEbookDetail(object sender, RoutedEventArgs e)
        {
            try
            {
                if (listBook.SelectedItems.Count == 1)
                {
                    EbookForDisplay selectedItem = (EbookForDisplay) listBook.SelectedItem;
                    Ebook tempEbook = selectedItem.Ebook;
                    listBoxDialogPresenter.Show(new BookInformation(_dao.Dto, tempEbook, this), tempEbook.Title);
                }
                else
                {
                    Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(SelectEbookWarn));
                }
            }
            catch (Exception ex)
            {
                Utilities.ShowErrorMesBox(String.Format(ResourceReader.GetResourceContent(UpdateEbookError), ex.Message));
            }
        }


        private List<EbookForDisplay> TransformEbook(List<Ebook> listEbook)
        {
            List<EbookForDisplay> rtList = new List<EbookForDisplay>();
            foreach (var tempEbook in listEbook)
            {
                EbookForDisplay temp = new EbookForDisplay();
                string iconPath = FileIcon;
                temp.FileType = iconPath;
                if (tempEbook.Type == Constants.EbookType.Pdf)
                {
                    iconPath = PdfIcon;
                    temp.FileType = iconPath;
                }
                else if (tempEbook.Type == Constants.EbookType.Epub)
                {
                    iconPath = EpubIcon;
                    temp.FileType = iconPath;
                }
                temp.Title = tempEbook.Title;
                temp.Author = tempEbook.Author;
                temp.GroupInText = tempEbook.GroupInText;
                temp.Ebook = tempEbook;
                rtList.Add(temp);
            }

            return rtList;
        }

        private void HandleBtAddBook(object sender, RoutedEventArgs e)
        {
            try
            {
                listBoxDialogPresenter.Show(new BookInformation(_dao.Dto, this),Constants.CommonCharacters.Empty);
            }
            catch (Exception ex)
            {
                Utilities.ShowErrorMesBox(String.Format(ResourceReader.GetResourceContent(AddEbookError), ex.Message));
            }
        }

        private void HandleGroupClick(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (GroupTreeView.SelectedItem != null)
            {
                try
                {
                    NewTreeViewItem selectedTreeViewItem = (NewTreeViewItem) ((TreeView) sender).SelectedItem;
                    List<EbookGroup> tempGroup = new List<EbookGroup>();
                    string groupName =
                        selectedTreeViewItem.ItemHeader.Split(Constants.CommonCharacters.NgoacDon)[0];
                    _ebookGroup = _dao.SelectEbookGroup(groupName);
                    tempGroup.Add(_ebookGroup);
                    RebindBookListData(tempGroup);
                }
                catch (Exception)
                {
                    BookInGroup selectedTreeViewItem = (BookInGroup) ((TreeView) sender).SelectedItem;
                    List<EbookGroup> tempGroup = new List<EbookGroup>();
                    _ebookGroup = selectedTreeViewItem.Parent;
                    tempGroup.Add(selectedTreeViewItem.Parent);
                    RebindBookListData(tempGroup);
                }
            }
        }
    }

    public class BookInGroup
    {
        public Ebook Source;
        public EbookGroup Parent;
        private string _bookName;
        private string _fileType;

        public string BookName
        {
            get { return _bookName; }
            set { _bookName = value; }
        }

        public string FileType
        {
            get { return _fileType; }
            set { _fileType = value; }
        }
    }

    public class EbookForDisplay
    {
        private string _fileType;
        private string _title;
        private string _author;
        private string _groupInText;
        private Ebook _ebook;

        public Ebook Ebook
        {
            get { return _ebook; }
            set { _ebook = value; }
        }

        public string FileType
        {
            get { return _fileType; }
            set { _fileType = value; }
        }

        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }

        public string Author
        {
            get { return _author; }
            set { _author = value; }
        }

        public string GroupInText
        {
            get { return _groupInText; }
            set { _groupInText = value; }
        }
    }
}